use image::GenericImageView;
use sdl2::pixels::PixelMasks;
use sdl2::rect::Rect;
use sdl2::render::{Texture, TextureCreator, WindowCanvas};
use sdl2::surface::Surface;
use sdl2::video::{Window, WindowContext};
use std::path::Path;

use crate::config::*;

pub fn load_png_as_texture<'a>(texture_creator: &'a TextureCreator<WindowContext>) -> Texture<'a> {
    let filepath =  TC_DIGITS_PNG_FILE_PATH;
    let img = match image::open(&Path::new(&filepath)) {
        Ok(img) => img,
        Err(_) => {
            // eprintln!("Could not load file {}", filepath);
            std::process::exit(1);
        }
    };

    let (png_width, png_height) = img.dimensions();
    let mut png_data = img.to_rgba8().into_raw();

    let surface = Surface::from_data_pixelmasks(
        png_data.as_mut_slice(),
        png_width,
        png_height,
        png_width * 4,
        &PixelMasks {
            bpp: 32,
            rmask: 0x000000FF,
            gmask: 0x0000FF00,
            bmask: 0x00FF0000,
            amask: 0xFF000000,
        },
    )
    .unwrap();

    let digits_texture = texture_creator
        .create_texture_from_surface(surface)
        .unwrap();
    digits_texture
}

pub fn initial_pen(
    window: &Window,
    pen_x: &mut i32,
    pen_y: &mut i32,
    user_scale: f32,
    fit_scale: &mut f32,
) {
    let (w, h) = window.size();

    let text_aspect_ratio = TEXT_WIDTH as f64 / TEXT_HEIGHT as f64;
    let window_aspect_radio = w as f64 / h as f64;
    *fit_scale = if text_aspect_ratio > window_aspect_radio {
        w as f32 / TEXT_WIDTH as f32
    } else {
        h as f32 / TEXT_HEIGHT as f32
    };

    let effective_digit_width = (CHAR_WIDTH as f32 * user_scale * *fit_scale).floor() as i32;
    let effective_digit_height = (CHAR_HEIGHT as f32 * user_scale * *fit_scale).floor() as i32;
    *pen_x = w as i32 / 2 - effective_digit_width * CHARS_COUNT as i32 / 2;
    *pen_y = h as i32 / 2 - effective_digit_height / 2;
}

pub fn render_digit_at(
    renderer: &mut WindowCanvas,
    texture: &Texture,
    digit_index: usize,
    wiggle_index: usize,
    pen_x: &mut i32,
    pen_y: &mut i32,
    user_scale: f32,
    fit_scale: f32,
) {
    let effective_digit_width = (CHAR_WIDTH as f32 * user_scale * fit_scale).floor() as i32;
    let effective_digit_height = (CHAR_HEIGHT as f32 * user_scale * fit_scale).floor() as i32;
    let src_rect = Rect::new(
        (digit_index * CHAR_WIDTH as usize) as i32,
        (wiggle_index * CHAR_HEIGHT as usize) as i32,
        SPRITE_CHAR_WIDTH,
        SPRITE_CHAR_HEIGHT,
    );

    let dst_rect = Rect::new(
        *pen_x,
        *pen_y,
        effective_digit_width as u32,
        effective_digit_height as u32,
    );

    renderer.copy(texture, src_rect, dst_rect).unwrap();
    *pen_x += effective_digit_width;
}
